package thread;

import java.util.PriorityQueue;
import java.util.concurrent.*;

/**
 *
 * 1.ArrayBlockingQueue：ArrayBlockingQueue是基于数组实现的，通过初始化时设置数组长度，是一个有界队列，
 * 而且ArrayBlockingQueue和LinkedBlockingQueue不同的是，ArrayBlockingQueue只有一个锁对象，
 * 而LinkedBlockingQueue是两个锁对象，一个锁对象会造成要么是生产者获得锁，要么是消费者获得锁，两者竞争锁，无法并行。
 *
 * 2.LinkedBlockingQueue：LinkedBlockingQueue是基于链表实现的，和ArrayBlockingQueue不同的是，大小可以初始化设置，
 * 如果不设置，默认设置大小为Integer.MAX_VALUE，LinkedBlockingQueue有两个锁对象，可以并行处理。
 *
 * 3.DelayQueue：DelayQueue是基于优先级的一个无界队列，队列元素必须实现Delayed接口，支持延迟获取，元
 * 素按照时间排序，只有元素到期后，消费者才能从队列中取出。
 *
 * 4.PriorityBlockingQueue：PriorityBlockingQueue是基于优先级的一个无界队列，底层是基于数组存储元素的，元素按照优选级顺序存储，
 * 优先级是通过Comparable的compareTo方法来实现的（自然排序），和其他堵塞队列不同的是，其只会堵塞消费者，不会堵塞生产者，数组会不断扩容，
 * 这就是一个彩蛋，使用时要谨慎。
 *
 * 5.SynchronousQueue：SynchronousQueue是一个特殊的队列，其内部是没有容器的，所以生产者生产一个数据，就堵塞了，必须等消费者消费后，
 * 生产者才能再次生产，称其为队列有点不合适，现实生活中，多个人才能称为队，一个人称为队有些说不过去。
 *
 * 当阻塞队列是空时，往队列中获取元素的操作（消费者）将会被阻塞
 * 当阻塞队列是满时，往队列里添加元素（生产者）将会被阻塞
 *
 *  为什么需要blockingQueen
 *  好处：我们不需要关系什么时候需要阻塞线程，什么时候需要唤醒线程
 *
 *  offer()如果队列满，阻塞
 *  poll()取值，如果取不到返回null
 *  take()取值，如果取不到返回，阻塞
 *
 * @author ycz
 * @date 2021/6/15
 */
public class BolckingQueueTest {

    public static void main(String[] args) throws Exception{
        desc();
//        test();
    }

    public static void test() throws InterruptedException {
        PriorityQueue<String> priorityQueue = new PriorityQueue<>();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(1);
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(2);
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(3);
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(4);
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(5);
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(6);
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<1000;i++){
                    priorityQueue.offer("666");
                }
            }
        }).start();
        Thread.sleep(5000L);
        System.out.println("priorityQueue.size()=="+priorityQueue.size());
    }

    public static void desc() throws Exception {
        // 由数组结构组成的有界阻塞队列
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(5);
        // 插入 队列满后直接抛出异常
        System.out.println(arrayBlockingQueue.add("1"));
        // 插入 队列满后不抛出异常
        System.out.println(arrayBlockingQueue.offer("2"));
        // 如果队列满，阻塞5s
        System.out.println(arrayBlockingQueue.offer("3",5L,TimeUnit.SECONDS));
        System.out.println(arrayBlockingQueue.offer("4",5L,TimeUnit.SECONDS));
        System.out.println(arrayBlockingQueue.offer("5",5L,TimeUnit.SECONDS));

        // 检查
        System.out.println("peek=="+arrayBlockingQueue.peek());


        // 移除 成功返回出队的元素，没队列里面没有就返回null
        System.out.printf("", arrayBlockingQueue.remove());
        System.out.println("poll==="+arrayBlockingQueue.poll());
        System.out.println("poll==="+arrayBlockingQueue.poll());
        System.out.println("poll==="+arrayBlockingQueue.poll());
        System.out.println("poll==="+arrayBlockingQueue.poll());
        System.out.println("poll==="+arrayBlockingQueue.poll());
        System.out.println("poll==="+arrayBlockingQueue.poll());
        System.out.println("arrayBlockingQueue.size()=="+arrayBlockingQueue.size());
//        System.out.printf("", arrayBlockingQueue.remove("2"));
//        System.out.printf("", arrayBlockingQueue.remove("2"));



        // 由链表结构组成的有界队列（默认值为Integer.MAX_VALUE）的阻塞队列
        LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(100);

        // 支持优先级排序的无界阻塞队列
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(((o1, o2) -> o1.compareTo(o2)));
        // PriorityQueue<SyncGoods> syncGoods = new PriorityQueue<>((int) total, (o1, o2) ->
        // o2.getCreateTime().compareTo(o1.getCreateTime()));
        priorityQueue.offer(666);
        priorityQueue.offer(669);
        priorityQueue.offer(688);
        priorityQueue.offer(677);
        priorityQueue.offer(655);
        priorityQueue.offer(600);
        priorityQueue.offer(44);
        priorityQueue.remove();
        while (!priorityQueue.isEmpty()){
            System.out.println("=======0000==="+priorityQueue.poll());;
        }

        System.out.println("priorityQueue.size()=="+priorityQueue.size());

        System.out.println(priorityQueue.peek());
        System.out.printf("====", priorityQueue.peek());

        // 使用优先级队列实现的延迟无界阻塞队列
        DelayQueue<Delayed> delayeds = new DelayQueue<>();

        // 不存储元素的阻塞队列，也即单个原少的队列
        SynchronousQueue<Object> synchronousQueue = new SynchronousQueue<>();

        // 由链表结果组成的无界阻塞队列
        LinkedTransferQueue<Object> linkedTransferQueue = new LinkedTransferQueue<>();

        // 由链表结构组成的双向阻塞队列
        LinkedBlockingQueue<Object> blockingQueue = new LinkedBlockingQueue<>();


    }


}
